package com.zapi.ai.service;

import com.zapi.ai.model.ApiMetadata;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.*;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * API扫描服务 - 扫描所有Controller接口
 */
@Slf4j
@Service
public class ApiScannerService {
    
    @Autowired
    private ApplicationContext applicationContext;
    
    /** 存储所有API元数据 */
    private List<ApiMetadata> allApis = new ArrayList<>();
    
    /** API索引（用于快速查找） */
    private Map<String, ApiMetadata> apiIndex = new HashMap<>();
    
    /** 扫描是否已完成 */
    private volatile boolean scanned = false;
    
    /**
     * 监听Spring容器刷新完成事件，此时所有Bean已初始化完成
     */
    @EventListener(ContextRefreshedEvent.class)
    public void onApplicationEvent(ContextRefreshedEvent event) {
        if (!scanned) {
            scanApis();
            scanned = true;
        }
    }
    
    /**
     * 扫描所有API
     */
    private void scanApis() {
        log.info("开始扫描系统API...");
        
        // 获取所有标注了@RestController的Bean
        Map<String, Object> controllers = applicationContext.getBeansWithAnnotation(RestController.class);
        
        for (Map.Entry<String, Object> entry : controllers.entrySet()) {
            String beanName = entry.getKey();
            Object controller = entry.getValue();
            Class<?> controllerClass = controller.getClass();
            
            // 获取真实的类（处理CGLIB代理）
            if (controllerClass.getName().contains("$$")) {
                controllerClass = controllerClass.getSuperclass();
            }
            
            scanController(controllerClass);
        }
        
        log.info("API扫描完成，共扫描到 {} 个API", allApis.size());
    }
    
    /**
     * 扫描单个Controller
     */
    private void scanController(Class<?> controllerClass) {
        // 获取Controller的基础路径
        RequestMapping baseMapping = controllerClass.getAnnotation(RequestMapping.class);
        String basePath = baseMapping != null && baseMapping.value().length > 0 
                ? baseMapping.value()[0] : "";
        
        // 获取Controller的模块名称
        Api apiAnnotation = controllerClass.getAnnotation(Api.class);
        String module = apiAnnotation != null && apiAnnotation.tags().length > 0 
                ? apiAnnotation.tags()[0] : controllerClass.getSimpleName();
        
        // 扫描所有方法
        for (Method method : controllerClass.getDeclaredMethods()) {
            ApiMetadata metadata = scanMethod(method, basePath, module);
            if (metadata != null) {
                allApis.add(metadata);
                String key = metadata.getMethod() + ":" + metadata.getPath();
                apiIndex.put(key, metadata);
            }
        }
    }
    
    /**
     * 扫描单个方法
     */
    private ApiMetadata scanMethod(Method method, String basePath, String module) {
        ApiMetadata metadata = new ApiMetadata();
        metadata.setModule(module);
        
        // 获取API操作描述
        ApiOperation apiOperation = method.getAnnotation(ApiOperation.class);
        if (apiOperation != null) {
            metadata.setOperation(apiOperation.value());
            metadata.setDescription(apiOperation.notes());
        } else {
            metadata.setOperation(method.getName());
        }
        
        // 获取HTTP方法和路径
        String httpMethod = null;
        String path = null;
        
        if (method.isAnnotationPresent(GetMapping.class)) {
            GetMapping mapping = method.getAnnotation(GetMapping.class);
            httpMethod = "GET";
            path = mapping.value().length > 0 ? mapping.value()[0] : "";
        } else if (method.isAnnotationPresent(PostMapping.class)) {
            PostMapping mapping = method.getAnnotation(PostMapping.class);
            httpMethod = "POST";
            path = mapping.value().length > 0 ? mapping.value()[0] : "";
        } else if (method.isAnnotationPresent(PutMapping.class)) {
            PutMapping mapping = method.getAnnotation(PutMapping.class);
            httpMethod = "PUT";
            path = mapping.value().length > 0 ? mapping.value()[0] : "";
        } else if (method.isAnnotationPresent(DeleteMapping.class)) {
            DeleteMapping mapping = method.getAnnotation(DeleteMapping.class);
            httpMethod = "DELETE";
            path = mapping.value().length > 0 ? mapping.value()[0] : "";
        } else if (method.isAnnotationPresent(RequestMapping.class)) {
            RequestMapping mapping = method.getAnnotation(RequestMapping.class);
            httpMethod = mapping.method().length > 0 ? mapping.method()[0].name() : "GET";
            path = mapping.value().length > 0 ? mapping.value()[0] : "";
        } else {
            // 不是HTTP端点方法
            return null;
        }
        
        metadata.setMethod(httpMethod);
        metadata.setPath(basePath + path);
        
        // 扫描参数
        List<ApiMetadata.ApiParameter> parameters = new ArrayList<>();
        for (Parameter parameter : method.getParameters()) {
            ApiMetadata.ApiParameter apiParam = scanParameter(parameter);
            if (apiParam != null) {
                parameters.add(apiParam);
            }
        }
        metadata.setParameters(parameters);
        
        return metadata;
    }
    
    /**
     * 扫描参数
     */
    private ApiMetadata.ApiParameter scanParameter(Parameter parameter) {
        ApiMetadata.ApiParameter apiParam = new ApiMetadata.ApiParameter();
        apiParam.setName(parameter.getName());
        apiParam.setType(parameter.getType().getSimpleName());
        
        // 检查参数注解
        if (parameter.isAnnotationPresent(RequestParam.class)) {
            RequestParam requestParam = parameter.getAnnotation(RequestParam.class);
            apiParam.setLocation("query");
            apiParam.setRequired(requestParam.required());
            if (!requestParam.defaultValue().equals("\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n")) {
                apiParam.setDefaultValue(requestParam.defaultValue());
            }
            if (!requestParam.value().isEmpty()) {
                apiParam.setName(requestParam.value());
            }
        } else if (parameter.isAnnotationPresent(PathVariable.class)) {
            PathVariable pathVariable = parameter.getAnnotation(PathVariable.class);
            apiParam.setLocation("path");
            apiParam.setRequired(true);
            if (!pathVariable.value().isEmpty()) {
                apiParam.setName(pathVariable.value());
            }
        } else if (parameter.isAnnotationPresent(RequestBody.class)) {
            apiParam.setLocation("body");
            apiParam.setRequired(true);
        } else {
            return null; // 跳过其他类型的参数
        }
        
        // 获取参数描述
        if (parameter.isAnnotationPresent(ApiParam.class)) {
            ApiParam apiParamAnnotation = parameter.getAnnotation(ApiParam.class);
            apiParam.setDescription(apiParamAnnotation.value());
        }
        
        return apiParam;
    }
    
    /**
     * 获取所有API
     */
    public List<ApiMetadata> getAllApis() {
        return new ArrayList<>(allApis);
    }
    
    /**
     * 根据关键词搜索API
     */
    public List<ApiMetadata> searchApis(String keyword) {
        if (keyword == null || keyword.trim().isEmpty()) {
            return getAllApis();
        }
        
        String lowerKeyword = keyword.toLowerCase();
        return allApis.stream()
                .filter(api -> 
                    api.getOperation().toLowerCase().contains(lowerKeyword) ||
                    api.getModule().toLowerCase().contains(lowerKeyword) ||
                    api.getPath().toLowerCase().contains(lowerKeyword)
                )
                .collect(Collectors.toList());
    }
    
    /**
     * 根据模块获取API
     */
    public List<ApiMetadata> getApisByModule(String module) {
        return allApis.stream()
                .filter(api -> api.getModule().equals(module))
                .collect(Collectors.toList());
    }
    
    /**
     * 生成AI可理解的API文档
     */
    public String generateApiDocumentation() {
        StringBuilder doc = new StringBuilder();
        doc.append("系统可用API列表：\n\n");
        
        // 按模块分组
        Map<String, List<ApiMetadata>> apisByModule = allApis.stream()
                .collect(Collectors.groupingBy(ApiMetadata::getModule));
        
        for (Map.Entry<String, List<ApiMetadata>> entry : apisByModule.entrySet()) {
            doc.append("【").append(entry.getKey()).append("】\n");
            for (ApiMetadata api : entry.getValue()) {
                doc.append(api.toFunctionDescription()).append("\n");
            }
            doc.append("\n");
        }
        
        return doc.toString();
    }
    
    /**
     * 获取API详情
     */
    public ApiMetadata getApi(String method, String path) {
        String key = method + ":" + path;
        return apiIndex.get(key);
    }
}

